home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / vtkerma1.arc / MSSEND.ASM < prev    next >
Assembly Source File  |  1986-02-13  |  33KB  |  1,121 lines

  1.     PAGE 59, 132
  2.  
  3.     TITLE MSSEND -- Module to Send files
  4.  
  5. ; Update 13 Jan 86
  6.  
  7. IF1
  8.  %OUT >> Starting pass 1
  9. ELSE
  10.  %OUT >> Starting pass 2
  11. ENDIF
  12.  
  13.     PUBLIC spar, rpar, error, error1, nout, send, flags, trans, pack
  14.     PUBLIC dodec, doenc, curchk, inichk, packlen, send11
  15.  
  16.     INCLUDE msdefs.h    
  17.  
  18. spmin    equ    20        ; Minimum packet size.
  19. spmax    equ    94        ; Maximum packet size.
  20.  
  21. datas     segment    public 'datas'
  22.     extrn    DTA:byte, data:byte, fcb:byte, cpfcb:byte, filbuf:byte
  23.     extrn    decbuf:byte, chrcnt:word, bufpnt:word, comand:byte
  24.     extrn    rptq:byte, origr:byte, rptct:byte, rptval:byte
  25.  
  26. flags    flginfo    <>
  27. trans    trinfo    <>
  28. pack    pktinfo <>
  29. crlf    db    cr,lf,'$'
  30. erms14  db    'Unable to receive an acknowledgment$'
  31. erms15  db    '? File not found',cr,lf,'$'
  32.  
  33. remmsg1    db    'Remote '
  34.     Program_name
  35.     db    ': File not found$'
  36. erms20    db    'Remote '
  37.     Program_name
  38.     db    ': Unable to send init packet$'
  39. erms21    db    'Remote '
  40.     Program_name
  41.     db    ': Unable to send file header$'
  42. erms22    db    'Remote '
  43.     Program_name
  44.     db    ': Unable to send data$'
  45. erms23    db    'Remote '
  46.     Program_name
  47.     db    ': Unable to send end-of-file packet$'
  48. erms24    db    'Remote '
  49.     Program_name
  50.     db    ': Unable to send break packet$'
  51. infms2  db    cr,'             Sending: In progress$'
  52. infms3  db    'Completed$'
  53. infms4  db    'Failed$'
  54. infms6  db    'Interrupted$'
  55. infms7    db    cr,' Percent transferred: 100%$'
  56. filhlp  db      ' Input file spec (possibly wild)$'
  57. filmsg    db    ' File name to use on target system or confirm with'
  58.     db    ' carriage return$'
  59.  
  60. curchk    db    0        ; Use to store checksum length.
  61. inichk    db    1        ; Original or set checksum length.
  62. chrptr  dw    ?        ; Position in character buffer.
  63. fcbpt    dw    ?        ; Position in FCB.
  64. datptr  dw    ?        ; Position in packet data buffer.
  65. siz    dw    ?        ; Size of data from gtchr.
  66. temp    dw    0
  67. temp4    dw    0
  68. sendas    dw    50 dup(0)    ; Buffer for file name.
  69. difnam    db    0        ; Send under different name?
  70. difsiz    db    0        ; Size of new file name.
  71. asmsg    db    ' as $'
  72. datas    ends
  73.  
  74. code    segment    public
  75.  
  76.     EXTRN serini:near, serrst:near, comnd:near, init:near, EOT_bells:NEAR
  77.     EXTRN spack:near, rpack:near, gtnfil:near, gtchr:near, ClearL:NEAR
  78.     EXTRN getfil:near, clrfln:near, cxmsg:near
  79.     EXTRN encode:near, nulref:near, decode:near, nulr:near
  80.     EXTRN errpack:near, updrtr:near, clrmod:near, fcbcpy:near
  81.     EXTRN perpos:near, Show_error:NEAR, Say_aborted:NEAR
  82.     EXTRN Show_status:NEAR, Show_retries:NEAR, Show_packets:NEAR
  83.     EXTRN Close_transfer_screen:NEAR
  84.  
  85.     assume    cs:code,ds:datas
  86.  
  87. ;    This routine sets up the data for init packet (either the
  88. ;    Send_init or ACK packet).
  89.  
  90. RPAR    PROC    NEAR
  91.     mov ah,trans.rpsiz    ; Get the receive packet size.
  92.     add ah,' '        ; Add a space to make it printable.
  93.     mov [bx],ah        ; Put it in the packet.
  94.     mov ah,trans.rtime    ; Get the receive packet time out.
  95.     add ah,' '        ; Add a space.
  96.     mov 1[bx],ah        ; Put it in the packet.
  97.     mov ah,trans.rpad    ; Get the number of padding chars.
  98.     add ah,' '
  99.     mov 2[bx],ah        ; Put it in the packet.
  100.     mov ah,trans.rpadch    ; Get the padding char.
  101.     add ah,100O        ; Uncontrol it.
  102.     and ah,7FH
  103.     mov 3[bx],ah        ; Put it in the packet.
  104.     mov ah,trans.reol    ; Get the EOL char.
  105.     add ah,' '
  106.     mov 4[bx],ah        ; Put it in the packet.
  107.     mov ah,trans.rquote    ; Get the quote char.
  108.     mov 5[bx],ah        ; Put it in the packet.
  109.     mov ah,trans.ebquot    ; Get 8-bit quote char. [21b]
  110.     mov 6[bx],ah        ; Add it to the packet. [21b] 
  111.     mov ah,trans.chklen    ; Length of checksum.
  112.     add ah,48        ; Make into a real digit.
  113.     mov 7[bx],ah
  114.     mov ah,rptq        ; Repeat quote char.
  115.     cmp ah,0        ; Null means no.
  116.     jne rpar0
  117.     mov ah,' '        ; Send a blank instead.
  118. rpar0:    mov 8[bx],ah
  119.     mov ah,trans.rcaps    ; Capabilities
  120.     add ah,' '        ; Printable
  121.     mov 9[bx],ah        ; Set them up
  122.     mov ah, 10        ; Ten pieces of data
  123.     ret
  124. RPAR    ENDP
  125.  
  126. ;    This routine reads in all the send_init packet information.
  127.  
  128. SPAR    PROC    NEAR
  129.     cmp ax,1
  130.     jge sparx
  131.     mov ah,dspsiz        ; Data not supplied by host, use default.
  132.     jmp sparx2
  133. sparx:    mov temp4,ax        ; Save the number of arguments.
  134.     mov ah,trans.spsiz
  135.     cmp ah,dspsiz        ; Is current value the default?
  136.     jne sparx2        ; No, assume changed by user.
  137.     mov ah,[bx]        ; Get the max packet size.
  138.     sub ah,' '        ; Subtract a space.
  139.     cmp ah,spmin        ; Can't be below the minimum.
  140.     jge sparx1
  141.     mov ah,spmin
  142.     jmp sparx2
  143. sparx1:    cmp ah,spmax        ; Or above the maximum.
  144.     jle sparx2
  145.     mov ah,spmax
  146. sparx2:    mov trans.spsiz,ah    ; Save it.
  147.     mov ax,temp4
  148.     cmp al,2        ; Fewer than two pieces?
  149.     jge spar0
  150.     mov ah,dstime        ; Data not supplied by host, use default.
  151.     jmp spar02
  152. spar0:     mov ah,trans.stime
  153.     cmp ah,dstime        ; Is current value the default?
  154.     jne spar02        ; No, assume changed by user.
  155.     mov ah,1[bx]        ; Get the timeout value.
  156.     sub ah,' '        ; Subtract a space.
  157.     cmp ah,0
  158.     ja spar01        ; Must be non-negative.
  159.     mov ah,0
  160. spar01:    cmp ah,trans.rtime    ; Same as other side's timeout.
  161.     jne spar02
  162.     add ah,5        ; If so, make it a little different.
  163. spar02:    mov trans.stime,ah    ; Save it.
  164.     mov ax,temp4
  165.     cmp al,3        ; Fewer than three pieces?
  166.     jge spar1
  167.     mov ah,dspad        ; Data not supplied by host, use default.
  168.     jmp spar11
  169. spar1:    mov ah,trans.spad
  170.     cmp ah,dspad        ; Is current value the default?
  171.     jne spar11        ; No, assume changed by user.
  172.     mov ah,2[bx]        ; Get the number of padding chars.
  173.     sub ah,' '
  174.     cmp ah,0
  175.     ja spar11        ; Must be non-negative.
  176.     mov ah,0
  177. spar11:    mov trans.spad,ah
  178.     mov ax,temp4
  179.     cmp al,4        ; Fewer than four pieces?
  180.     jge spar2
  181.     mov ah,dspadc        ; Data not supplied by host, use default.
  182.     jmp spar21
  183. spar2:    mov ah,trans.spadch
  184.     cmp ah,dspadc        ; Is current value the default?
  185.     jne spar21        ; No, assume changed by user.
  186.     mov ah,3[bx]        ; Get the padding char.
  187.     add ah,100O        ; Re-controlify it.
  188.     and ah,7FH
  189.     cmp ah,del        ; Delete?
  190.     je spar21        ; Yes, then it's OK.
  191.     cmp ah,0
  192.     jge spar20
  193.     mov ah,0        ; Below zero is no good.
  194.     jmp spar21        ; Use zero (null).
  195. spar20:    cmp ah,31        ; Is it a control char?
  196.     jle spar21        ; Yes, then OK.
  197.     mov ah,0        ; No, use null.
  198. spar21:    mov trans.spadch,ah
  199.     mov ax,temp4
  200.     cmp al,5        ; Fewer than five pieces?
  201.     jge spar3
  202.     mov ah,dseol        ; Data not supplied by host, use default.
  203.     jmp spar31
  204. spar3:  mov ah,trans.seol
  205.     cmp ah,dseol        ; Is current value the default?
  206.     jne spar31        ; No, assume changed by user.
  207.     mov ah,4[bx]        ; Get the EOL char.
  208.     sub ah,' '
  209.     cmp ah,0
  210.     jge spar30        ; Cannot be negative.
  211.     mov ah,cr        ; If it is, use default of carriage return.
  212.     jmp spar31
  213. spar30:    cmp ah,31        ; Is it a control char?
  214.     jle spar31        ; Yes, then use it.
  215.     mov ah,cr        ; Else, use the default.
  216. spar31:    mov trans.seol,ah
  217.     mov ax,temp4
  218.     cmp al,6        ; Fewer than six pieces?
  219.     jge spar4
  220.     mov ah,dsquot        ; Data not supplied by host, use default.
  221.     jmp spar41
  222. spar4:    mov ah,trans.squote
  223.     cmp ah,dsquot        ; Is current value the default?
  224.     jne spar41        ; No, assume changed by user.
  225.     mov ah,5[bx]        ; Get the quote char.
  226.     cmp ah,' '        ; Less than a space?
  227.     jge spar40
  228.     mov ah,dsquot        ; Yes, use default.
  229.     jmp spar41
  230. spar40:    cmp ah,'~'        ; Must also be less then a tilde.
  231.     jle spar41
  232.     mov ah,dsquot        ; Else, use default.
  233. spar41:    mov trans.squote,ah
  234.     cmp al,7        ; Fewer than seven pieces? [21b begin]
  235.     jge spar5
  236.     mov trans.ebquot,'Y'    ; Data not supplied by host, use default.
  237.     jmp spar51
  238. spar5:    mov ah,6[bx]        ; Get other sides 8-bit quote request.
  239.     call doquo        ; And set quote char.  [21b end]
  240. spar51:    cmp al,8        ; Fewer than eight pieces?
  241.     jge spar6
  242.     mov trans.chklen,1
  243.     jmp spar61
  244. spar6:    mov ah,inichk
  245.     mov trans.chklen,ah    ; Checksum length we really want to use.
  246.     mov ah,7[bx]        ; Get other sides checksum length.
  247.     call dochk        ; Determine what size to use.
  248. spar61:    mov rptq,0        ; Set this up
  249.     cmp al,9        ; Fewer than nine pieces?
  250.      jl spar71        ;  Fewer, use default we just set up
  251.  
  252.     mov ah,8[bx]        ; Get other side's repeat count prefix
  253.     mov ch,drpt
  254.     call dorpt
  255.  
  256. spar71:    cmp al,10        ; Fewer than ten pieces?
  257.      jge spar8        ;  Have them ...
  258.  
  259.     mov trans.scaps,0    ; Say no special caps
  260.     ret
  261.  
  262. spar8:    mov ah,9[bx]        ; Pick up the value we got
  263.     sub ah,' '        ; Convert from printable
  264.     mov trans.scaps, ah    ; Store in Trans structure
  265.     ret
  266.  
  267. SPAR    ENDP
  268.  
  269. ; Set 8-bit quote character based on my capabilities and the other
  270. ; Kermit's request.   [21b]
  271.  
  272. DOQUO    PROC    NEAR
  273.     cmp trans.ebquot,'N'    ; Can I do 8-bit quoting at all?
  274.     je dq3            ; No - so forget it.
  275.     cmp trans.ebquot,'Y'    ; Can I do it if requested?
  276.     jne dq0            ; No - it's a must that I do it.
  277.     mov trans.ebquot,ah    ; Do whatever he wants.
  278.     jmp dq1
  279. dq0:    cmp ah,'Y'        ; I need quoting - can he do it?
  280.     je dq1            ; Yes - then all is settled.
  281.     cmp ah,'N'        ; No - then don't quote.
  282.     je dq3
  283.     cmp ah,trans.ebquot    ; Both need quoting - chars must match.
  284.     jne dq3
  285. dq1:    mov ah,trans.ebquot
  286.     cmp ah,'Y'        ; If Y or N, don't validate prefix.
  287.     je dq2
  288.     cmp ah,'N'
  289.     je dq2
  290.     call prechk        ; Is it in range 33-62, 96-126?
  291.      mov ah,'Y'        ; Failed, don't do quoting.
  292.      nop
  293.     cmp ah,trans.rquote    ; Same prefix?
  294.     je dq3            ; Not allowed, so don't do quoting. 
  295.     cmp ah,trans.squote    ; Same prefix here?
  296.     je dq3            ; This is illegal too.
  297.     mov trans.ebquot,ah    ; Remember what we decided on.
  298. dq2:    ret
  299. dq3:    mov trans.ebquot,'N'    ; Quoting will not be done.
  300.     ret
  301. DOQUO    ENDP
  302.  
  303. ; Check if prefix in AH is in the proper range: 33-62, 96-126. 
  304. ; RSKP if so else RETURN.
  305. prechk:    cmp ah,33
  306.     jge prec0        ; It's above 33.
  307.     ret
  308. prec0:    cmp ah,62
  309.     jg prec1
  310.     jmp rskp        ; And below 62.  OK.
  311. prec1:    cmp ah,96
  312.     jge prec2        ; It's above 96.
  313.     ret
  314. prec2:    cmp ah,126
  315.     jg prec3
  316.     jmp rskp        ; And below 126.  OK.
  317. prec3:    ret
  318.  
  319. ; Set checksum length. 
  320. dochk:    cmp ah,'1'        ; Must be 1, 2, or 3.
  321.     jl doc1
  322.     cmp ah,'3'
  323.     jle doc2
  324. doc1:    mov ah,'1'
  325. doc2:    sub ah,48        ; Don't want it printable.
  326.     cmp ah,trans.chklen    ; Do we want the same thing?
  327.     je dochk0        ; Yes, then we're done.
  328.     mov trans.chklen,1    ; No, use single character checksum.
  329. dochk0:    ret            ; Just return for now.
  330.  
  331. ; Set repeat count quote character.  The one used must be different than
  332. ; the control and eight-bit quote characters.  Also, both sides must 
  333. ; use the same character.
  334. dorpt:    call prechk        ; Is it in the valid range?
  335.      mov ah,0        ; No, don't use their value. 
  336.      nop
  337.     cmp ah,trans.squote    ; Same as the control quote char?
  338.     je dorpt0        ; Yes, that's illegal, no repeats.
  339.     cmp ah,trans.rquote    ; How about this one?
  340.     je dorpt0        ; No good.
  341.     cmp ah,trans.ebquot    ; Same as eight bit quote char?
  342.     je dorpt0        ; Yes, that's illegal too, no repeats.
  343.     cmp ah,ch        ; Are we planning to use the same char?
  344.     jne dorpt0        ; No, that's no good either.
  345.     mov rptq,ch        ; Use repeat quote char now.
  346. dorpt0:    ret
  347.  
  348. ;    Send command
  349.  
  350. SEND    PROC    NEAR
  351.     mov comand.cmcr,0    ; Filename must be specified.
  352.     mov difnam,0        ; Assume we'll use original filename.
  353.     mov flags.wldflg,0    ; Re-initialize every time.
  354.     mov ah,cmifi        ; Parse an input file spec.
  355.     mov dx,offset fcb    ; Give the address for the FCB.
  356.     mov bx,offset filhlp    ; Text of help message.
  357.     call comnd
  358.      jmp RSkp        ;  Give up on bad parse.
  359.     cmp flags.wldflg,0FFH    ; Any wildcards seen?
  360.      je send1        ; Yes, get a confirm.
  361.  
  362.     mov bx,offset sendas    ; See if want to send file under dif name.
  363.     mov dx,offset filmsg    ; In case user needs help.
  364.     mov ah,cmtxt
  365.     call comnd
  366.      jmp RSkp
  367.     cmp ah,0        ; Different name supplied?
  368.      je send0a        ;  No
  369.  
  370.     mov difnam,1        ; Yes - send different filename.
  371.     mov difsiz,ah        ; Remember length of new name.
  372.     jmp SHORT send10    ; Join common code
  373.  
  374. send0a:    mov ah,sfirst        ; Get the first file.
  375.     mov dx,offset fcb
  376.     int dos            ; Make sure file exists
  377.  
  378.     cmp al,0FFH        ; Any found?
  379.      jne send10        ;  Yes, move on
  380.  
  381.     mov ah,prstr        ; No, complain
  382.     mov dx,offset erms15
  383.     int dos
  384.  
  385.     jmp rskp
  386.  
  387. send1:  mov ah,cmcfm
  388.     call comnd        ; Get a confirm.
  389.      jmp r            ;  Didn't get a confirm.
  390.  
  391. Send10:    call serini        ; Initialize serial port. [14]
  392.     call Init        ; Clear the line and initialize the buffers
  393.  
  394.     mov dx, OFFSET Infms2    ; Sending: In progress
  395.     call Show_status    ; Say what mode we are in
  396.  
  397.     call Send11        ; Call our routine to send the file
  398.      nop            ;  He skips
  399.      nop
  400.      nop
  401.  
  402.     jmp RSkp        ; Return skip
  403.  
  404. Send11: mov flags.droflg,0    ; Reset flags from fn parsing. [21a]
  405.     mov flags.nmoflg,0    ; Reset flags from fn parsing. [21a]
  406.     mov ah,sfirst        ; Get the first file.
  407.     mov dx,offset fcb
  408.     int dos
  409.     cmp al,0FFH        ; Any found?
  410.     jne send12
  411.     cmp pack.state,'R'    ; was this from a remote GET?
  412.     jne sen11a        ; no, print error and continue
  413.     mov bx,offset remmsg1    ; else get error message
  414.     call errpack        ; go complain
  415.     jmp abort        ; and abort this
  416. sen11a:    mov ah,prstr
  417.     mov dx,offset erms15
  418.     int dos
  419.     jmp rskp
  420.  
  421.     PUBLIC Send12
  422.  
  423. send12: cmp flags.wldflg,0    ; Any wildcards.      [7 start]
  424.     je send16        ; Nope, so no problem.
  425.     mov bx,offset fcb    ; Remember what FCB looked like.
  426.     mov di,offset cpfcb
  427.     mov cl,37        ; Size of FCB.
  428.     call fcbcpy
  429.     mov di,offset fcb+1    ; Copy filename    from DTA to FCB.
  430.     mov bx,offset DTA+1
  431.     mov cl,11
  432.     call fcbcpy                    ; [7 end]
  433.  
  434. send16:    mov pack.pktnum,0    ; Set the packet number to zero.
  435.     mov pack.numtry,0    ; Set the number of tries to zero.
  436.     mov pack.numpkt,0     ; Set the number of packets to zero.
  437.     mov pack.numrtr,0    ; Set the number of retries to zero.
  438.     mov pack.state,'S'    ; Set the state to send initiate.
  439.  
  440.     mov dx, OFFSET Infms2    ; Sending: In progress
  441.     call Show_status    ; Say what mode we are in
  442.  
  443.     call Show_packets    ; Display packet count
  444.     call ClearL        ; Make sure display looks right
  445.  
  446. Send2:    call Show_packets    ; Display packet count
  447.  
  448.     cmp pack.state,'D'    ; Are we in the data send state?
  449.     jne send3
  450.     call sdata
  451.     jmp send2
  452. send3:  cmp pack.state,'F'    ; Are we in the file send state?
  453.     jne send4
  454.     call sfile        ; Call send file.
  455.     jmp send2
  456. send4:  cmp pack.state,'Z'    ; Are we in the EOF state?
  457.     jne send5
  458.     call seof
  459.     jmp send2
  460. send5:  cmp pack.state,'S'    ; Are we in the send initiate state?
  461.     jne send6
  462.     call sinit
  463.     jmp send2
  464. send6:  cmp pack.state,'B'    ; Are we in the eot state?
  465.     jne send7
  466.     call seot
  467.     jmp send2
  468.  
  469. send7:  cmp pack.state,'C'    ; Are we in the send complete state?
  470.      jne send8
  471.  
  472.     cmp Flags.RemFlg, 0    ; remote mode?
  473.      jne Send9a        ;  yes, no printing
  474.  
  475.     cmp Flags.cxzflg, 0    ; completed normally?
  476.      jne Send7a        ;  no, don't bother with this
  477.  
  478.     call PerPos        ; Note that we are now 100% done
  479.     mov ah, PrStr
  480.     mov dx, OFFSET infms7
  481.     int Dos
  482.  
  483.     mov dx, OFFSET InfMs3    ; Message saying success
  484.     jmp SHORT Send7b
  485.  
  486. Send7a:    mov dx, OFFSET infms6    ; Say was interrupted
  487.  
  488. Send7b:    call Show_status    ; Display the message, whatever it is
  489.     call EOT_bells        ; Make noise if enabled
  490.  
  491.     jmp SHORT Send9
  492.  
  493. ; Hit some error, should have been already noted onscreen
  494.  
  495. send8:    mov dx,offset infms4    ; Plus a little cuteness
  496.     call Show_status    ; Say we failed
  497.  
  498. send9:    call Close_transfer_screen
  499.  
  500. Send9a:    jmp rskp
  501.  
  502. SEND    ENDP
  503.  
  504.  
  505. ;    Send routines
  506.  
  507. ;    Send initiate
  508.  
  509.  
  510. SINIT    PROC    NEAR
  511.     cmp pack.numtry,imxtry    ; Have we reached the maximum number of tries?
  512.     jl sinit2
  513.     mov dx,offset erms14
  514.     call Show_error
  515.     mov bx,offset erms20
  516.     call errpack        ; Send error packet just in case.
  517.     jmp abort        ; Change the state to abort.
  518. sinit2: inc pack.numtry        ; Save the updated number of tries.
  519.     mov bx,offset data    ; Get a pointer to our data block.
  520.     call rpar        ; Set up the parameter information.
  521.     xchg ah,al
  522.     mov ah,0
  523.     mov pack.argbk1,ax    ; Save the number of arguments.
  524.     mov ax,pack.numpkt    ; Get the packet number.
  525.     mov pack.argblk,ax
  526.     mov ah,trans.chklen
  527.     mov curchk,ah        ; Store checksum length we want to use.
  528.     mov trans.chklen,1    ; Send init checksum is always 1 char.
  529.     mov ah,'S'        ; Send initiate packet.
  530.     call spack        ; Send the packet.
  531.      jmp abort
  532.     call rpack        ; Get a packet.
  533.      jmp sini23        ; Trashed packet don't change state, retry.
  534.     push ax
  535.     mov ah,curchk
  536.     mov trans.chklen,ah    ; Checksum length we want to use.
  537.     pop ax
  538.     cmp ah,'Y'        ; ACK?
  539.     jne sinit3        ; If not try next.
  540.     mov ax,pack.pktnum    ; Get the packet number.
  541.     cmp ax,pack.argblk    ; Is it the right packet number?
  542.     je sini22
  543.     ret            ; If not try again.
  544. sini22: inc ax            ; Increment the packet number.
  545.     and ax,3FH        ; Turn off the two high order bits.
  546.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  547.     inc pack.numpkt        ; Increment the number of packets.
  548.     mov ax,pack.argbk1    ; Get the number of pieces of data.
  549.     mov bx,offset data    ; Pointer to the data.
  550.     call spar        ; Read in the data.
  551.     call packlen        ; Get max send packet size. [21b]
  552.     mov ah,pack.numtry    ; Get the number of tries.
  553.     mov pack.oldtry,ah    ; Save it.
  554.     mov pack.numtry,0    ; Reset the number of tries.
  555.     mov pack.state,'F'    ; Set the state to file send.
  556.     call getfil        ; Open the file.
  557.      jmp abort        ;  Something is wrong, die.
  558.     ret
  559.  
  560. %OUT >> About half way through source file
  561.  
  562. sini23:    mov ah,curchk        ; Restore desired checksum length.
  563.     mov trans.chklen,ah
  564.     call updrtr        ; Update retry counter.
  565.     ret            ; And retry.
  566. sinit3: cmp ah,'N'        ; NAK?
  567.     jne sinit4        ; If not see if its an error.
  568.     inc pack.numrtr        ; Increment the number of retries
  569.     jmp Show_retries    ; Show the number of retries onscreen
  570.  
  571. sinit4: cmp ah,'E'        ; Is it an error packet.
  572.     jne sinit5
  573.     call error
  574. sinit5: jmp abort
  575. SINIT    ENDP
  576.  
  577.  
  578.  
  579. ;    Send file header
  580.  
  581. SFILE    PROC    NEAR
  582.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  583.     jl sfile1
  584.     mov dx,offset erms14
  585.     call Show_error
  586.     mov bx,offset erms21
  587.     call errpack        ; Send error packet just in case.
  588.     jmp abort        ; Change the state to abort.
  589. sfile1: inc pack.numtry        ; Increment it.
  590.     mov flags.cxzflg,0    ; Clear ^X,^Z flag. 
  591.     mov datptr,offset data  ; Get a pointer to our data block.
  592.     mov bx,offset fcb+1    ; Pointer to file name in FCB.
  593.     mov fcbpt,bx        ; Save position in FCB.
  594.     mov cl,0        ; Counter for chars in file name.
  595.     mov ch,0        ; Counter for number of chars in FCB.
  596. sfil11:    cmp ch,8H        ; Ninth char?
  597.     jne sfil12
  598.     mov ah,'.'
  599.     mov bx,datptr
  600.     mov [bx],ah        ; Put dot in data packet.    
  601.     inc bx
  602.     mov datptr,bx        ; Save new position in data packet.
  603.     inc cl
  604. sfil12:    inc ch
  605.     cmp ch,0CH        ; Twelve?
  606.     jns sfil13
  607.     mov bx,fcbpt
  608.     mov ah,[bx]        ; Get char of filename.
  609.     inc bx
  610.     mov fcbpt,bx        ; Save position in FCB.
  611.     cmp ah,'!'        ; Is it a good char?
  612.     jl sfil11        ; If not, get the next.
  613.     mov bx,datptr
  614.     mov [bx],ah        ; Put char in data buffer.
  615.     inc cl            ; Increment counter.
  616.     inc bx
  617.     mov datptr,bx        ; Save new position. 
  618.     jmp sfil11        ; Get another char.
  619. sfil13: mov ch,0
  620.     cmp flags.remflg,0    ; remote mode?
  621.     jne sfil13a        ; yes, no printing.
  622.     push cx            ; Don't forget the size.
  623.     mov bx,datptr
  624.     mov ah,'$'
  625.     mov [bx],ah        ; Put dollar sign for printing.
  626.     call clrfln
  627.     mov ah,prstr
  628.     mov dx,offset data    ; Print file name.
  629.     int dos
  630.     pop cx
  631. sfil13a:cmp difnam,0        ; Sending file under different name.
  632.     je sfl13x        ; No, so don't give new name.
  633.     call newfn
  634. sfl13x:    call doenc        ; Do encoding.
  635.     mov ax,pack.pktnum    ; Get the packet number.
  636.     mov pack.argblk,ax
  637.     mov ah,'F'        ; File header packet.
  638.     call spack        ; Send the packet.
  639.      jmp abort
  640.     call rpack        ; Get a packet.
  641.      jmp tryagn        ; Trashed packet don't change state, retry.
  642.     call dodec        ; Do all decoding.
  643.     cmp ah,'Y'        ; ACK?
  644.     jne sfile2        ; If not try next.
  645.     mov ax,pack.pktnum    ; Get the packet number.
  646.     cmp ax,pack.argblk
  647.     je sfil14
  648.     ret            ; If not hold out for the right one.
  649. sfil14: inc ax            ; Increment the packet number.
  650.     and ax,3FH        ; Turn off the two high order bits.
  651.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  652.     inc pack.numpkt        ; Increment the number of packets.
  653.     mov ah,pack.numtry    ; Get the number of tries.
  654.     mov pack.oldtry,ah    ; Save it.
  655.     mov pack.numtry,0    ; Reset the number of tries.
  656.  
  657. sfil15: mov ah,0        ; Get a zero.
  658.     mov bx,offset fcb
  659.     add bx,20H
  660.     mov [bx],ah        ; Set the record number to zero.
  661. ;    mov flags.eoflag,ah    ; Indicate not EOF.  (Done in GETFIL).
  662.     mov ah,0FFH
  663.     mov flags.filflg,ah    ; Indicate file buffer empty.
  664.     call gtchr
  665.      jmp sfil16        ; Error go see if its EOF.
  666.      nop
  667.     jmp sfil17        ; Got the chars, proceed.
  668.  
  669. sfil16: cmp ah,0FFH        ; Is it EOF?
  670.     je sfl161
  671.     jmp abort        ; If not give up.
  672.  
  673. sfl161: mov ah,'Z'        ; Set the state to EOF.
  674.     mov pack.state,ah
  675.     ret
  676.  
  677. sfil17: mov siz,ax
  678.     call Send_attribute    ; Maybe send an attribute packet
  679.     mov pack.state,'D'    ; Set the state to data send.
  680.     ret
  681.  
  682. Send_attribute:
  683.     ret            ; NOP for now
  684.  
  685. sfile2: cmp ah,'N'        ; NAK?
  686.     jne sfile3        ; Try if error packet.
  687.     inc pack.numrtr        ; Increment the number of retries
  688.     call Show_retries
  689.     mov ax,pack.pktnum    ; Get the present packet number.
  690.     inc ax            ; Increment.
  691.     and ax,03FH        ; Account for wraparound.  [18]
  692.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  693.     jz sfil14        ; Just as good as a ACK; go to the ACK code.
  694.     ret            ; If not go try again.
  695.  
  696. sfile3: cmp ah,'E'        ; Is it an error packet.
  697.     jne sfile4
  698.     call error
  699.  
  700. sfile4: jmp abort
  701.  
  702. SFILE    ENDP
  703.  
  704.  
  705. ;    Send data
  706.  
  707. SDATA    PROC    NEAR
  708.     cmp flags.cxzflg,0    ; Have we seen ^X or ^Z?
  709.     je sdata2        ; Nope, just continue.
  710.     cmp flags.cxzflg,'C'    ; Stop it all? [25]
  711.     jne sdata1        ; It was a ^X or ^Z.
  712.     call Say_aborted    ; Note this "error" onscreen
  713.     mov pack.state,'A'    ; It was a ^C -- abort [25]
  714.     ret
  715. sdata1:    mov pack.state,'Z'    ; Else, abort sending the file.
  716.     ret
  717. sdata2: cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  718.     jl sdata3
  719.     mov dx,offset erms14
  720.     call Show_error        ; Display error message
  721.     mov bx,offset erms22
  722.     call errpack        ; Send error packet just in case.
  723.     jmp abort        ; Change the state to abort.
  724. sdata3: inc pack.numtry        ; Increment it.
  725.     mov datptr,offset data  ; Get a pointer to our data block.
  726.     mov chrptr,offset filbuf ; Pointer to chars to be sent.
  727.     mov cx,siz        ; number to transfer
  728.     mov si,chrptr        ; source of characters
  729.     mov di,datptr        ; destination
  730.     cmp flags.eofcz,0    ; stopping on ctl-z's?
  731.     jz sdata6        ; no, do blind copy
  732. sdata4:    lodsb            ; get a byte
  733.     cmp al,'Z'-40H        ; is it a ctl-z?
  734.     je sdata5        ; yes, break loop
  735.     stosb            ; else copy it
  736.     loop sdata4        ; and keep going
  737. sdata5:    mov ax,siz        ; size to send
  738.     sub ax,cx        ; minus actually sent...
  739.     jmp short sdata7
  740. sdata6:    rep movsb        ; just copy data
  741.     mov ax,siz        ; this is how many were moved
  742. sdata7:    mov pack.argbk1,ax
  743.     mov ax,pack.pktnum    ; Get the packet number.
  744.     mov pack.argblk,ax
  745.     mov ah,'D'        ; Data packet.
  746.     call spack        ; Send the packet.
  747.      jmp tryagn        ; if can't send it, retry before giving up
  748.     call rpack        ; Get a packet.
  749.      jmp tryagn        ; Trashed packet don't change state, retry.
  750.     call dodec        ; Do all decoding.
  751.     cmp ah,'Y'        ; ACK?
  752.     jne sdat14        ; If not try next.
  753.     mov ax,pack.pktnum    ; Get the packet number.
  754.     cmp ax,pack.argblk    ; Is it the right packet number?
  755.     jz sdata8
  756.     ret            ; If not hold out for the right one.
  757. sdata8: inc ax            ; Increment the packet number.
  758.     and ax,3FH        ; Turn off the two high order bits.
  759.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  760.     inc pack.numpkt        ; Increment the number of packets.
  761.     mov ah,pack.numtry    ; Get the number of tries.
  762.     mov pack.oldtry,ah    ; Save it.
  763.     mov pack.numtry,0    ; Reset the number of tries.
  764.     cmp pack.argbk1,1    ; Does the ACK contain data?
  765.     jne sdat11        ; Nope, so continue.
  766.     mov bx,offset data    ; If yes, check the data field.
  767.     mov ah,[bx]        ; Pick it up.
  768.     cmp ah,'X'        ; Other side requests ^X?
  769.     jne sdata9        ; Nope.
  770.     jmp sdat10        ; And leave.
  771. sdata9: cmp ah,'Z'        ; Other side requests ^Z?
  772.     jne sdat11        ; Nope.
  773. sdat10:    mov flags.cxzflg,ah    ; Yes remember it.
  774.     mov pack.state,'Z'    ; Abort sending file(s).
  775.     ret
  776. sdat11: call gtchr
  777.      jmp sdat12        ; Error go see if its EOF.
  778.     mov siz,ax        ; Save the size of the data gotten.
  779.     ret
  780.  
  781. sdat12: cmp ah,0FFH        ; Is it EOF?
  782.     je sdat13
  783.     jmp abort        ; If not give up.
  784.  
  785. sdat13: mov pack.state,'Z'    ; Set the state to EOF.
  786.     ret
  787. sdat14: cmp ah,'N'        ; NAK?
  788.     jne sdat15        ; See if is an error packet.
  789.     inc pack.numrtr        ; Increment the number of retries
  790.     call Show_retries    ; Display it
  791.     mov ax,pack.pktnum    ; Get the present packet number.
  792.     inc ax            ; Increment.
  793.     and ax,03FH        ; Account for wraparound.  [18]
  794.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  795.     jz sdata8        ; Just as good as ACK; goto ACK code.
  796.     ret            ; If not go try again.
  797. sdat15: cmp ah,'E'        ; Is it an error packet.
  798.     jne sdat16
  799.     call error
  800. sdat16: jmp abort
  801. SDATA    ENDP
  802.  
  803.  
  804. ;    Send EOF
  805.  
  806. SEOF    PROC    NEAR
  807.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  808.     jl seof1
  809.     mov dx,offset erms14
  810.     call Show_error        ; Display an error message
  811.     mov bx,offset erms23
  812.     call errpack        ; Send error packet just in case.
  813.     jmp abort        ; Change the state to abort.
  814. seof1:  inc pack.numtry        ; Increment it.
  815.     mov ax,pack.pktnum    ; Get the packet number.
  816.     mov pack.argblk,ax
  817.     mov pack.argbk1,0    ; No data.
  818.     cmp flags.cxzflg,0    ; Seen a ^X or ^Z?
  819.     je seof11        ; Nope, send normal EOF packet.
  820.     mov bx,offset data    ; Get data area of packet.
  821.     mov ah,'D'        ; Use "D" for discard.
  822.     mov [bx],ah        ; And add it to the packet.
  823.     mov pack.argbk1,1    ; Set data size to 1.
  824. seof11:    mov cx,pack.argbk1    ; Put size in CX.
  825.     call doenc        ; Encode the packet.
  826.     mov ah,'Z'        ; EOF packet.
  827.     call spack        ; Send the packet.
  828.      jmp abort
  829.     call rpack        ; Get a packet.
  830.      jmp tryagn        ;  Trashed packet don't change state, retry.
  831.     call dodec        ; Do decoding.
  832.     cmp ah,'Y'        ; ACK?
  833.     jne seof2        ; If not try next.
  834.     mov ax,pack.pktnum    ; Get the packet number.
  835.     cmp ax,pack.argblk    ; Is it the right packet number?
  836.     jz seof12
  837.     ret            ; If not hold out for the right one.
  838. seof12: inc ax            ; Increment the packet number.
  839.     and ax,3FH        ; Turn off the two high order bits.
  840.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  841.     inc pack.numpkt        ; Increment the number of packets.
  842.     mov ah,pack.numtry    ; Get the number of tries.
  843.     mov pack.oldtry,ah    ; Save it.
  844.     mov pack.numtry,0    ; Reset the number of tries.
  845.     mov ah,closf        ; Close the file.
  846.     mov dx,offset fcb
  847.     int dos
  848.     call gtnfil        ; Get the next file.
  849.      jmp seof13        ;  No more.
  850.     mov pack.state,'F'    ; Set the state to file send.
  851.  
  852. ; Is this right ???????
  853.     mov flags.cxzflg,0    ; Reset the flag.
  854.     ret
  855.  
  856. seof13: mov pack.state,'B'    ; Set the state to EOT.
  857.     ret
  858. seof2:  cmp ah,'N'        ; NAK?
  859.     jne seof3        ; Try and see if its an error packet.
  860.     inc pack.numrtr        ; Increment the number of retries
  861.     call Show_retries    ; Display it
  862.     mov ax,pack.pktnum    ; Get the present packet number.
  863.     inc ax            ; Increment.
  864.     and ax,03FH        ; Account for wraparound.  [18]
  865.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  866.     jz seof12        ; Just as good as a ACK; go to the ACK code.
  867.     ret            ; If not go try again.
  868. seof3:  cmp ah,'E'        ; Is it an error packet?
  869.     jne seof4
  870.     call error
  871. seof4:  jmp abort
  872. SEOF    ENDP
  873.  
  874.  
  875. ;    Send EOT
  876.  
  877. SEOT    PROC    NEAR
  878.     cmp pack.numtry,maxtry    ; Have we reached the maximum number of tries?
  879.     jl seot1
  880.     mov dx,offset erms14
  881.     call Show_error        ; Display error
  882.     mov bx,offset erms24
  883.     call errpack        ; Send error packet just in case.
  884.     jmp abort        ; Change the state to abort.
  885. seot1:  inc pack.numtry        ; Increment it.
  886.     mov ax,pack.pktnum    ; Get the packet number.
  887.     mov pack.argblk,ax
  888.     mov pack.argbk1,0    ; No data.
  889.     mov cx,pack.argbk1
  890.     call doenc        ; Encode packet.
  891.     mov ah,'B'        ; EOF packet.
  892.     call spack        ; Send the packet.
  893.      jmp abort
  894.     call rpack        ; Get a packet.
  895.      jmp tryagn        ; Trashed packet don't change state, retry.
  896.     call dodec        ; Decode packet.
  897.     cmp ah,'Y'        ; ACK?
  898.     jne seot2        ; If not try next.
  899.     mov ax,pack.pktnum    ; Get the packet number.
  900.     cmp ax,pack.argblk    ; Is it the right packet number?
  901.     jz seot12
  902.     ret            ; If not hold out for the right one.
  903. seot12: inc ax            ; Increment the packet number.
  904.     and ax,3FH        ; Turn off the two high order bits.
  905.     mov pack.pktnum,ax    ; Save modulo 64 of the number.
  906.     inc pack.numpkt        ; Increment the number of packets.
  907.     mov ah,pack.numtry    ; Get the number of tries.
  908.     mov pack.oldtry,ah    ; Save it.
  909.     mov pack.numtry,0    ; Reset the number of tries.
  910.     mov pack.state,'C'    ; Set the state to file send.
  911.     ret
  912. seot2:  cmp ah,'N'        ; NAK?
  913.     jne seot3        ; Is it error.
  914.     inc pack.numrtr        ; Increment the number of retries
  915.     call Show_retries    ; Display it
  916.     mov ax,pack.pktnum    ; Get the present packet number.
  917.     inc ax            ; Increment.
  918.     and ax,03FH        ; Account for wraparound.  [18]
  919.     cmp ax,pack.argblk    ; Is the packet's number one more than now?
  920.     jz seot12        ; Just as good as a ACK; go to the ACK code.
  921.     ret            ; If not go try again.
  922. seot3:  cmp ah,'E'        ; Is it an error packet.
  923.     jne seot4
  924.     call error
  925. seot4:  jmp abort
  926. SEOT    ENDP
  927.  
  928. tryagn:    call updrtr
  929.     ret
  930.  
  931. newfn:    mov ah,prstr
  932.     mov dx,offset asmsg
  933.     int dos
  934.     mov ah,dconio
  935.     mov si,offset sendas    ; Buffer where the name is.
  936.     mov di,offset data
  937.     mov ch,0
  938.     mov cl,difsiz        ; Length of name.
  939. newf0:    lodsb            ; Get a char.
  940.     cmp al,61H
  941.     jb newf1        ; Leave alone if less than 'a'?
  942.     cmp al,7AH
  943.     ja newf1        ; Leave alone if over 'z'.
  944.     sub al,20H        ; Uppercase the letters.
  945. newf1:    stosb
  946.     mov dl,al
  947.     cmp flags.remflg,0    ; should we print?
  948.     jne newf2        ; no, we're in remote mode.
  949.     int dos            ; Print them.
  950. newf2:    loop newf0
  951.     mov ch,0
  952.     mov cl,difsiz        ; Reset the length field.
  953.     ret
  954.  
  955. ; Do encoding.  Expectx CX to be the data size.
  956. doenc:    jcxz doen0
  957.     mov chrcnt,cx        ; Number of chars in filename.
  958.     mov bx,offset data    ; Source of data.
  959.     mov bufpnt,bx
  960.     mov bx,offset nulref    ; Null routine for refilling buffer.
  961.     mov ah,rptq
  962.     mov origr,ah        ; Save repeat prefix here.
  963.     mov rptct,1        ; Number of times char is repeated.
  964.     mov rptval,0        ; Value of repeated char.
  965.     call encode        ; Make a packet with size in AX.
  966.      nop
  967.      nop
  968.      nop
  969.     mov pack.argbk1,ax    ; Save number of char in filename.
  970.     mov cx,ax
  971.     call movpak        ; Move to data part of packet.
  972. doen0:    ret
  973.  
  974. ; CX is set before this is called.
  975. movpak:    push es
  976.     mov ax,ds
  977.     mov es,ax
  978.     mov si,offset filbuf    ; Move from here
  979.     mov di,offset data    ; to here
  980.     repne movsb
  981.     pop es
  982.     ret
  983.  
  984. ; Do decoding.
  985. dodec:    cmp pack.argbk1,0
  986.     je dodc0
  987.     push ax            ; Save packet size.
  988.     mov cx,pack.argbk1    ; Size of data.
  989.     mov bx,offset data    ; Address of data.
  990.     mov ax,offset nulr    ; Routine to dump buffer (null routine).
  991.     mov bufpnt,offset decbuf  ; Where to put output.
  992.     mov chrcnt,80H        ; Buffer size.
  993.     call decode
  994.      nop     
  995.      nop     
  996.      nop     
  997.     call decmov        ; Move decoded data back to "data" buffer.
  998.      pop ax
  999. dodc0:    ret
  1000.  
  1001. ; Move decoded data from decode buffer back to "data". 
  1002. decmov:    push si
  1003.     push di
  1004.     push es
  1005.     mov ax,ds
  1006.     mov es,ax
  1007.     mov cx,bufpnt        ; Last char we added.
  1008.     sub cx,offset decbuf    ; Get actual number of characters.
  1009.     mov pack.argbk1,cx    ; Remember size of real data.
  1010.     lea si,decbuf        ; Data is here.
  1011.     lea di,data        ; Move to here.
  1012.     repne movsb        ; Copy the data.
  1013.     pop es
  1014.     pop di
  1015.     pop si
  1016.     ret
  1017.  
  1018. ;    Abort
  1019.  
  1020. ABORT    PROC    NEAR
  1021.     mov pack.state,'A'    ; Otherwise abort.
  1022.     ret
  1023. ABORT    ENDP
  1024.  
  1025. ; This is where we go if we get an error packet.  A call to ERROR 
  1026. ; positions the cursor and prints the message.  A call to ERROR1
  1027. ; just prints a CRLF and then the message.  [8]
  1028.  
  1029. ERROR    PROC
  1030.  
  1031.     mov pack.state,'A'    ; Set the state to abort.
  1032.  
  1033.     mov bx,pack.argbk1    ; Get the length of the data.
  1034.     add bx,offset data    ; Get to the end of the string.
  1035.     mov ah,'$'        ; Put a dollar sign at the end.
  1036.     mov [bx],ah
  1037.     mov dx,offset data    ; The error message
  1038.     jmp Show_error        ; Display the message and beep
  1039.  
  1040. ERROR    ENDP
  1041.  
  1042. Error1    PROC
  1043.  
  1044.     mov bx,pack.argbk1    ; Get the length of the data.
  1045.     add bx,offset data    ; Get to the end of the string.
  1046.     mov ah,'$'        ; Put a dollar sign at the end.
  1047.     mov [bx],ah
  1048.  
  1049.     mov ah, PrStr        ; Print the error message.
  1050.     mov dx, OFFSET data
  1051.     int dos
  1052.  
  1053.     mov dx, OFFSET crlf
  1054.     int dos
  1055.  
  1056.     ret
  1057.  
  1058. Error1    ENDP
  1059.  
  1060. ; Set the maximum data packet size. [21b]
  1061.  
  1062. PACKLEN    PROC    NEAR
  1063.     mov ah,trans.spsiz    ; Maximum send packet size. 
  1064.     sub ah,4        ; Size minus control info. 
  1065.     sub ah,trans.chklen    ; And minus checksum chars.
  1066.     sub ah,2        ; Leave room at end: 2 for possible #X.
  1067.     cmp trans.ebquot,'N'    ; Doing 8-bit quoting?
  1068.     je pack0        ; Nope so we've got our size.
  1069.     cmp trans.ebquot,'Y'
  1070.     je pack0        ; Not doing it in this case either.
  1071.     sub ah,1        ; Another 1 for 8th-bit quoting. 
  1072. pack0:    cmp rptq,0        ; Doing repeat character quoting?
  1073.     je pack1        ; Nope, so that's all for now.
  1074.     sub ah,2        ; Another 2 for repeat prefix.
  1075. pack1:    mov trans.maxdat,ah    ; Save max length for data field.
  1076.     ret
  1077. PACKLEN    ENDP
  1078.  
  1079.  ; Print the number in AX on the screen in decimal rather that hex. [19a]
  1080.  
  1081. NOUT     PROC    NEAR
  1082.     cmp flags.xflg,1    ; Writing to screen? [21c]
  1083.     je nout1        ; Yes, just leave. [21c]
  1084.     push ax
  1085.     push dx
  1086.     mov temp,10        ; Divide quotient by 10.
  1087.     mov dx,0        ; High order word should be zero.
  1088.     div temp        ; AX <-- Quo, DX <-- Rem.
  1089.     cmp ax,0        ; Are we done?    
  1090.     jz nout0        ; Yes.
  1091.     call nout        ; If not, then recurse.
  1092. nout0:    add dl,'0'        ; Make it printable.
  1093.     mov temp,ax
  1094.     mov ah,conout
  1095.     int dos    
  1096.     mov ax,temp
  1097.     pop dx
  1098.     pop ax
  1099. nout1:    ret            ; We're done. [21c]
  1100. NOUT    ENDP
  1101.  
  1102. ; Jumping to this location is like retskp.  It assumes the instruction
  1103. ;   after the call is a jmp addr.
  1104.  
  1105. RSKP    PROC    NEAR
  1106.     pop bp
  1107.     add bp,3
  1108.     push bp
  1109.     ret
  1110. RSKP    ENDP
  1111.  
  1112. ; Jumping here is the same as a ret.
  1113.  
  1114. R    PROC    NEAR
  1115.     ret
  1116. R    ENDP
  1117.  
  1118. code    ends 
  1119.     end
  1120. 
  1121.